/**
 * @file ha_mqtt.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2024-01-24
 *
 * @copyright Copyright (c) 2024
 *
*/
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ha_mqtt.h"
#include "bluficonfig.h"
#include "aiio_wifi.h"
#include "log.h"
#include "device_ctrl.h"
#define DBG_TAG "ha_mqtt"

unsigned char mac[6] = { 0 };
static aiio_err_t mqtt_event_cb(aiio_mqtt_event_handle_t event);
ha_devMsg_t homeAssistant_dev;
static aiio_mqtt_client_config_t mqtt_cfg;
aiio_mqtt_client_handle_t fd_client;
discovery_payload_t discovery_payload[10] = { 0 };
/**
 * @brief
 *
 * @param message
 * @param error_code
*/
static void log_error_if_nonzero(const char* message, int error_code)
{
    if (error_code != 0) {
        LOG_E("Last error %s: 0x%x", message, error_code);
    }
}
/**
 * @brief
 *
 * @param event
 * @return aiio_err_t
*/
static aiio_err_t mqtt_event_cb(aiio_mqtt_event_handle_t event)
{
    int32_t event_id;
    aiio_mqtt_client_handle_t client = event->client;
    event_id = event->event_id;
    LOG_I("Event dispatched, event_id=%d", event_id);
    int msg_id;
    switch ((aiio_mqtt_event_id_t)event_id) {
        case MQTT_EVENT_CONNECTED:
            LOG_I("MQTT_EVENT_CONNECTED");
            strcpy(homeAssistant_dev.mqtt_host, mqtt_cfg.host);
            strcpy(homeAssistant_dev.mqtt_username, mqtt_cfg.username);
            strcpy(homeAssistant_dev.mqtt_password, mqtt_cfg.password);
            LOG_D("homeAssistant_dev.wifi_ssid=%s", homeAssistant_dev.wifi_ssid);
            LOG_D("homeAssistant_dev.wifi_passsword=%s", homeAssistant_dev.wifi_password);
            LOG_D("homeAssistant_dev.mqtt_host=%s", homeAssistant_dev.mqtt_host);
            LOG_D("homeAssistant_dev.mqtt_username=%s", homeAssistant_dev.mqtt_username);
            LOG_D("homeAssistant_dev.mqtt_password=%s", homeAssistant_dev.mqtt_password);
            //连接成功，保存信息
            // if (!reset_flash_state)homeassistant_save_ha_deMsg(&homeAssistant_dev);

            homeAssistant_create_device(client, &discovery_payload[0], HA_DISCOVERY_SWITCH, "relay1");
            homeAssistant_create_device(client, &discovery_payload[1], HA_DISCOVERY_SWITCH, "relay2");
            homeAssistant_create_device(client, &discovery_payload[2], HA_DISCOVERY_SWITCH, "relay3");
            homeAssistant_create_device(client, &discovery_payload[3], HA_DISCOVERY_SWITCH, "relayall");
            homeAssistant_create_device(client, &discovery_payload[4], HA_DISCOVERY_SWITCH, "mod_work");
            homeAssistant_create_device(client, &discovery_payload[5], HA_DISCOVERY_SWITCH, "mod_outhome");
            homeAssistant_create_device(client, &discovery_payload[6], HA_DISCOVERY_SWITCH, "mod_sleep");
            homeAssistant_create_device(client, &discovery_payload[7], HA_DISCOVERY_SWITCH, "mod_vidio");
            homeAssistant_create_device(client, &discovery_payload[8], HA_DISCOVERY_SWITCH, "xiaomiSW");
            homeAssistant_create_device(client, &discovery_payload[9], HA_DISCOVERY_SWITCH, "HomeKitSW");
            //发布在线通知
            vTaskDelay(pdMS_TO_TICKS(50));
            homeassistant_send_status("online");
            //发送一次灯的状态
            vTaskDelay(pdMS_TO_TICKS(50));
            homeAssistant_send_state(client, &discovery_payload[0], 0);
            homeAssistant_send_state(client, &discovery_payload[1], 0);
            homeAssistant_send_state(client, &discovery_payload[2], 0);
            homeAssistant_send_state(client, &discovery_payload[3], 0);
            homeAssistant_send_state(client, &discovery_payload[4], 0);
            homeAssistant_send_state(client, &discovery_payload[5], 0);
            homeAssistant_send_state(client, &discovery_payload[6], 0);
            homeAssistant_send_state(client, &discovery_payload[7], 0);
            homeAssistant_send_state(client, &discovery_payload[8], 0);
            homeAssistant_send_state(client, &discovery_payload[9], 0);
            //订阅 HA的状态
            char* mqtt_discovery_topic = pvPortMalloc(256);
            memset(mqtt_discovery_topic, 0, 256);
            sprintf(mqtt_discovery_topic, "%s/status", HA_AUTOMATIC_DISCOVERY);
            msg_id = aiio_mqtt_client_subscribe(client, mqtt_discovery_topic, 0);

            vPortFree(mqtt_discovery_topic);
            break;
        case MQTT_EVENT_DISCONNECTED:
            LOG_I("MQTT_EVENT_DISCONNECTED");
            LOG_D("homeAssistant mqtt client host=%s", mqtt_cfg.host);
            LOG_D("homeAssistant mqtt client port=%d", mqtt_cfg.port);
            LOG_D("homeAssistant mqtt client uri=%s", mqtt_cfg.uri);
            LOG_D("homeAssistant mqtt client id=%s", mqtt_cfg.client_id);
            LOG_D("homeAssistant mqtt client user name=%s", mqtt_cfg.username);
            LOG_D("homeAssistant mqtt client password=%s", mqtt_cfg.password);
            // homeassistant_send_status("offline");
            break;
        case MQTT_EVENT_SUBSCRIBED:
            LOG_I("MQTT_EVENT_SUBSCRIBED, topic=%*.s msg_id=%d", event->topic_len, event->topic, event->msg_id);

            // msg_id = aiio_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
            // LOG_I("sent publish successful, msg_id=%d", msg_id);
            break;
        case MQTT_EVENT_UNSUBSCRIBED:
            LOG_I("MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_PUBLISHED:
            LOG_I("MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);

            break;
        case MQTT_EVENT_DATA:
            LOG_I("MQTT_EVENT_DATA");
            LOG_I("TOPIC=%.*s", event->topic_len, event->topic);
            LOG_I("DATA=%.*s", event->data_len, event->data);
            LOG_I("HomeAssistant event =%d", homeassistant_get_event(discovery_payload, event->topic, event->topic_len, event->data, event->data_len));

            switch (homeassistant_get_event(discovery_payload, event->topic, event->topic_len, event->data, event->data_len))
            {
                case HOMEASSISTANT_EVENT_ONLINE:
                    LOG_I("HomeAssistant event:HOMEASSISTANT_EVENT_ONLINE");
                    homeassistant_send_status("online");
                    break;
                case HOMEASSISTANT_EVENT_OFFLINE:
                    // aiio_mqtt_client_publish(client, discovery_payload.availability_topic, "offline", 7, 0, 1);
                    break;
                case HOMEASSISTANT_EVENT_RELY1_ON:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 1);
                    device_send_state_notify(DEVICE_STATE_RELAY1_ON, 0);
                    break;
                case HOMEASSISTANT_EVENT_RELY1_OFF:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 0);
                    device_send_state_notify(DEVICE_STATE_RELAY1_OFF, 0);
                    break;
                case HOMEASSISTANT_EVENT_RELY2_ON:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 1);
                    device_send_state_notify(DEVICE_STATE_RELAY2_ON, 0);
                    break;
                case HOMEASSISTANT_EVENT_RELY2_OFF:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 0);
                    device_send_state_notify(DEVICE_STATE_RELAY2_OFF, 0);
                    break;
                case HOMEASSISTANT_EVENT_RELY3_ON:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 1);
                    device_send_state_notify(DEVICE_STATE_RELAY3_ON, 0);
                    break;
                case HOMEASSISTANT_EVENT_RELY3_OFF:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 0);
                    device_send_state_notify(DEVICE_STATE_RELAY3_OFF, 0);
                    break;
                case HOMEASSISTANT_EVENT_RELY_ALL_ON:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 1);
                    device_send_state_notify(DEVICE_STATE_RELAY_ALL_ON, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_XIAOMISW_ON:
                    device_send_state_notify(DEVICE_STATE_XIAOMI_ON, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_XIAOMISW_OFF:
                    device_send_state_notify(DEVICE_STATE_XIAOMI_OFF, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_HOMEKITSW_ON:
                    device_send_state_notify(DEVICE_STATE_HOMEKIT_ON, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_HOMEKITSW_OFF:
                    device_send_state_notify(DEVICE_STATE_RHOMEKIT_OFF, 0);
                    break;
                case HOMEASSISTANT_EVENT_RELY_ALL_OFF:
                    // devLedCtrlValueFromPayload(event->data, event->data_len);
                    // homeAssistant_send_state(client, &discovery_payload[0], 0);
                    device_send_state_notify(DEVICE_STATE_RELAY_ALL_OFF, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_OUTHOME:
                    device_send_state_notify(DEVICE_STATE_MODE_OUTHOME, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_WORK:
                    device_send_state_notify(DEVICE_STATE_MODE_WORK, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_SLEEP:
                    device_send_state_notify(DEVICE_STATE_MODE_SLEEP, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_VIDIO:
                    device_send_state_notify(DEVICE_STATE_MODE_VIDIO, 0);
                    break;
                case HOMEASSISTANT_EVENT_MOD_OFF:
                    device_send_state_notify(DEVICE_STATE_MODE_NONE, 0);
                    break;

                default:
                    break;
            }
            break;
        case MQTT_EVENT_ERROR:
            LOG_I("MQTT_EVENT_ERROR");
            if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
                log_error_if_nonzero("reported from esp-tls", event->error_handle->aiio_tls_last_aiio_err);
                log_error_if_nonzero("reported from tls stack", event->error_handle->aiio_tls_stack_err);
                log_error_if_nonzero("captured as transport's socket errno", event->error_handle->aiio_transport_sock_errno);
                LOG_I("Last errno string (%s)", strerror(event->error_handle->aiio_transport_sock_errno));
            }
            break;
        default:
            LOG_I("Other event id:%d", event->event_id);
            break;
    }
    return AIIO_OK;
}

void ha_dev_mqtt_init(ha_devMsg_t* devMsg)
{

    if (devMsg==NULL) {
        LOG_E("HomeAssistant dev message buff is NULL!");
        return;
    }
    devMsg->dev_mac = pvPortMalloc(12);
    devMsg->dev_name = pvPortMalloc(32);
    devMsg->mqtt_host = pvPortMalloc(64);
    devMsg->mqtt_password = pvPortMalloc(512);

    devMsg->mqtt_username = pvPortMalloc(128);
    devMsg->port = CONFIG_MQTT_PORT;
    devMsg->wifi_ssid = pvPortMalloc(64);
    devMsg->wifi_password = pvPortMalloc(64);

    memset(devMsg->mqtt_host, 0, 64);
    memset(devMsg->mqtt_password, 0, 512);
    memset(devMsg->mqtt_username, 0, 128);
    memset(devMsg->dev_mac, 0, 12);
    memset(devMsg->dev_name, 0, 32);

    strcpy(devMsg->mqtt_host, CONFIG_MQTT_HOST);
    strcpy(devMsg->mqtt_password, "12345678");
    strcpy(devMsg->mqtt_username, CONFIG_DEVICE_TYPE);
    aiio_wifi_sta_mac_get(mac);

    mqtt_cfg.event_handle = mqtt_event_cb;
    mqtt_cfg.host = devMsg->mqtt_host;
    sprintf(devMsg->dev_name, "%s_%02x%02x", devMsg->mqtt_username, mac[4], mac[5]);
    sprintf(devMsg->dev_mac, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    mqtt_cfg.client_id = devMsg->dev_name;
    mqtt_cfg.username = devMsg->mqtt_username;
    mqtt_cfg.port = devMsg->port;
    mqtt_cfg.password = devMsg->mqtt_password;

    discovery_payload[0].availability_topic = pvPortMalloc(256);
    memset(discovery_payload[0].availability_topic, 0, 256);
    sprintf(discovery_payload[0].availability_topic, "%s/%s/status", HA_AUTOMATIC_DISCOVERY, devMsg->dev_mac);

    discovery_payload[1].availability_topic = pvPortMalloc(256);
    memset(discovery_payload[1].availability_topic, 0, 256);
    sprintf(discovery_payload[1].availability_topic, "%s/%s/status", HA_AUTOMATIC_DISCOVERY, devMsg->dev_mac);

    discovery_payload[2].availability_topic = pvPortMalloc(256);
    memset(discovery_payload[2].availability_topic, 0, 256);
    sprintf(discovery_payload[2].availability_topic, "%s/%s/status", HA_AUTOMATIC_DISCOVERY, devMsg->dev_mac);


    mqtt_cfg.lwt_qos = 0;
    mqtt_cfg.lwt_topic = discovery_payload[0].availability_topic;
    mqtt_cfg.lwt_msg = "offline";
    mqtt_cfg.lwt_msg_len = strlen("offline");
    mqtt_cfg.lwt_retain = 1;
    memset(&fd_client, 0, sizeof(aiio_mqtt_client_handle_t));
    fd_client = aiio_mqtt_client_init(&mqtt_cfg);

}

void ha_dev_mqtt_deint(void)
{
    if (fd_client==NULL) {
        LOG_E("fd_client is not init");
        return;
    }
    homeassistant_send_status("offline");
    LOG_W("HomeAssistant disconnect");
    vTaskDelay(pdMS_TO_TICKS(100));
    aiio_mqtt_client_disconnect(fd_client);
    LOG_W("MQTT disconnect");
    aiio_mqtt_client_stop(fd_client);
    // aiio_mqtt_client_destroy(fd_client);
}
/**
 * @brief
 *
 * @param devMsg
*/
void ha_dev_mqtt_connenct(void)
{
    if (fd_client==NULL)
    {
        LOG_E("HomeAssistant MQTT client in no init!");
        return;
    }
    aiio_mqtt_client_start(fd_client);
}